<template>
  <div class="main-todo" draggable="true">
    <input
      v-model.trim="content"
      @keyup.enter="handelAdd"
      class="add-todo"
      type="text"
      placeholder="What to do? ↵"
      autofocus
    />
    <label
      :class="[
        'select-all',
        completedQuantity == todos.length ? '' : 'un-select-all',
      ]"
      @click="handleSelectAll(completedQuantity == todos.length)"
    ></label>
    <div class="content-list">
      <draggable v-model="filterTodos" v-bind="{ animation: 300 }">
        <transition-group>
          <todo-item
            v-for="todo in filterTodos"
            :key="todo.id"
            :todo="todo"
            @toggle="handleToggle"
            @edit="handleUpdate"
            @delete="handleDelete"
          ></todo-item>
        </transition-group>
      </draggable>
    </div>

    <todo-info
      :infoShow="todos.length != 0"
      :clearShow="completedQuantity != 0"
      :total="total"
      @toggle="handleState"
      @clear="handleClear"
    ></todo-info>
  </div>
</template>

<script>
//导入拖拽组件
import draggable from 'vuedraggable'

//导入子组件
import TodoInfo from './coms/TodoInfo.vue'
import TodoItem from './coms/TodoItem.vue'

export default {
  name: 'MainTodo',
  components: {
    TodoInfo,
    TodoItem,
    draggable,
  },
  data() {
    return {
      todos: [
        // { id: 1, content: '待办1', completed: 0 },
      ],
      filterTodos: [],
      content: '',
      state: 'all',
    }
  },
  computed: {
    total() {
      return this.todos.filter((item) => item.completed == 0).length
    },
    completedQuantity() {
      //完成项数量
      return this.todos.filter((item) => item.completed == 1).length
    },
    filterData() {
      // 比在 handleState 中修改 filterTodos 高效，但与draggable的v-model冲突，拖拽无效
      switch (this.state) {
        case 'all':
          return this.todos
        case 'active':
          return this.todos.filter((item) => item.completed == 0)
        case 'completed':
          return this.todos.filter((item) => item.completed == 1)
        default:
          return this.todos
      }
    },
  },
  created() {
    this.getData()
  },
  methods: {
    getData() {
      // 在MainTodo组件被创建时, 自动执行
      // 发送ajax请求, 请求接口数据
      this.$http.get('http://localhost:3000/todos').then((res) => {
        // 解构res, 只关心data中的数据
        const { code, message, result } = res.data
        if (code == 0) {
          this.todos = result.reverse() //倒序
          this.handleState(this.state) //根据当前查看的状态为filterTodos赋值
        }
      })
    },
    handelAdd() {
      if (this.content == '') {
        alert('请输入待办内容')
        return
      }

      //发送ajax请求，调用添加接口 post/todos {content:'test'}
      this.$http
        .post('http://localhost:3000/todos', { content: this.content })
        .then((res) => {
          const { code, message, result } = res.data
          if (code == 0) {
            this.content = ''
            //重新获取数据
            this.getData()
          }
        })
    },
    handleToggle(id) {
      /* 
        根据id找到todos数组中对应的对象， 更新completed的值
          方法1：filter，返回数组
              const req = this.todos.filter((item) => {
                return item.id == id
              }) //返回数组
              console.log('req[0]', req[0]) //？
          方法2： find， 返回对象
      */
      const req = this.todos.find((item) => item.id == id)

      req.completed = req.completed ? 1 : 0

      //发送ajax，调用更新接口
      // put /todos/1 {completed: 0}
      this.$http.put('http://localhost:3000/todos/' + id, req).then((res) => {
        const { code } = res.data
        if (code == 0) {
          this.getData()
        }
      })
    },
    handleUpdate(id, content) {
      /* 
      vue.$emit('edit', '参1', '参2')有多个参数时：
      方法1： 模板中插件引用处，方法不写参数括号；方法定义处的括号内写上对应个数的形参
      方法2： 模板中插件引用出，方法参数写作：arguments；方法定义处用一个形参接收，格式为数组，使用为 形参[0]
      */

      // 1. 根据id查找需要修改的todo对象
      const todo = this.todos.find((item) => item.id == id)
      // 2. 更新todo对象的content的值
      todo.content = content

      // 3. 发送ajax请求, 调用put接口更新
      this.$http.put(`http://localhost:3000/todos/${id}`, todo).then((res) => {
        const { code } = res.data
        if (code == 0) {
          this.getData()
        }
      })
    },
    handleDelete(id) {
      // 发送ajax请求, 调用delete接口
      // delete /todos/1
      this.$http.delete(`http://localhost:3000/todos/${id}`).then((res) => {
        const { code } = res.data
        if (code == 0) {
          this.getData()
        }
      })
    },
    handleState(s) {
      this.state = s
      switch (s) {
        case 'all':
          this.filterTodos = this.todos
          break
        case 'active':
          this.filterTodos = this.todos.filter((item) => item.completed == 0)
          break
        case 'completed':
          this.filterTodos = this.todos.filter((item) => item.completed == 1)
          break
        default:
          this.filterTodos = this.todos
      }
    },
    handleClear() {
      // delete /todos?completed=1
      this.$http
        .delete('http://localhost:3000/todos?completed=1')
        .then((res) => {
          const { code } = res.data
          if (code == 0) {
            this.getData()
          }
        })
    },
    handleSelectAll(selected) {
      // 获取最大索引
      const maxIndex = this.todos.length - 1
      // 当前是否全选状态（以确定将todos设置为全选 或 全不选）
      const completed = selected ? 0 : 1

      this.todos.forEach((item, index) => {
        item.completed = completed
        this.$http
          .put(`http://localhost:3000/todos/${item.id}`, item)
          .then((res) => {
            const { code } = res.data
            if (code != 0) {
              return
            }
            if (maxIndex == index) {
              //遍历到最后一项（减少开销），重新加载数据。
              //写在回调函数外会受异步影响
              this.getData()
            }
          })
      })
    },
  },
}
</script>

<style lang="stylus">
@import '@/assets/styles/theme.styl';

.main-todo
  //css自定义属性，记录input与info的高度，服务于列表的自适应高度
  --other-height: 172px;
  position: relative;
  width: 60%;
  max-width: 900px;
  min-width: 600px;
  max-height: calc(100vh - var(--header-height) - var(--footer-height)); /* 100vh：浏览器高度 */
  margin: 0 auto;
  padding: 16px;
  background-color rgba(255,255,255,0.4);
  border-radius: 26px;
  box-shadow: 3px 3px 5px #aaa;

  .add-todo
    width: 100%;
    padding: 16px 16px 16px 60px;
    border: none;
    background-color: rgba(255,255,255,0.7);
    font-size: 24px;
    font-family: inherit; //防止font-weight失效
    color $cat
    outline: none;
    border-radius: 63px;
    box-sizing: border-box;
    // 区分placeholder和输入文本的样式
    &::placeholder
      font-weight: 100;
    &:focus
      box-shadow: 0 0 2px 2px $blue;

  // 列表的自适应高度与滚动条
  .content-list
    max-height: calc(100vh - var(--header-height) - var(--footer-height) - var(--other-height));
    overflow: auto;
    /* 滚动条的梅花 */
    &::-webkit-scrollbar
      /*滚动条整体样式*/
      width : 10px;  /*高宽分别对应横竖滚动条的尺寸*/
      height: 1px;
    &::-webkit-scrollbar-thumb
      /*滚动条里面小方块*/
      border-radius: 10px;
      box-shadow   : inset 0 0 5px rgba(0, 0, 0, 0.1);
      background   : $cat2;
    &::-webkit-scrollbar-track
      /*滚动条里面轨道*/
      box-shadow   : inset 0 0 5px rgba(0, 0, 0, 0.1);
      border-radius: 10px;
      background   : #ededed;

  //全选与否
  label.select-all
    position: absolute;
    top: 37px;
    left: 33px;
    &::after
      content: url('@/assets/images/全选.svg');
    &.un-select-all::after
      content: url('@/assets/images/未全选.svg');
</style>
